import axios, {
  type AxiosInstance,
  type AxiosRequestConfig,
  type AxiosResponse,
  type InternalAxiosRequestConfig,
  type AxiosError,
} from 'axios'
import qs from 'qs'
import { getToken, csrfToken } from '@/utils/auth'
import router from '@/router/index'
import type { BaseResponse, ErrorResponse, RequestConfig } from './types'

class HttpClient {
  private instance: AxiosInstance

  constructor(config: AxiosRequestConfig) {
    this.instance = axios.create(config)
    this.setupInterceptors()
  }

  private setupInterceptors(): void {
    // 请求拦截
    this.instance.interceptors.request.use(
      (config: InternalAxiosRequestConfig) => {
        // 让每个请求携带token-- ['authorization']为固定key
        if (getToken()) {
          config.headers['authorization'] = `Bearer ${getToken()}`
        }
        // 让每个请求携带csrfToken-- ['x-csrf-token']为固定key
        if (csrfToken()) {
          config.headers['x-csrf-token'] = csrfToken()
        }
        if (!config.params) {
          config.params = {}
        }
        config.params._ = new Date().getTime()

        // 如果是 GET 请求，并且 params 是一个对象，自动用 qs 处理
        if (config.method === 'get' && config.params) {
          config.paramsSerializer = () => qs.stringify(config.params, { indices: true })
        }
        return config
      },
      (error: AxiosError) => {
        return Promise.reject(error)
      },
    )

    // 响应拦截 - 修复类型问题
    this.instance.interceptors.response.use(
      (response: AxiosResponse<BaseResponse>) => {
        const { data } = response
        if (data.code !== 200) {
          ElMessage({
            message: `${data.code}:${data.msg}`,
            type: 'warning',
            grouping: true,
          })

          return Promise.reject({
            code: data.code,
            msg: data.msg,
            response,
          } as ErrorResponse)
        }
        // 明确返回类型
        return response
      },
      (error: AxiosError<ErrorResponse>) => {
        console.log('error=====s')
        console.log(error.config?.url)
        console.log(error.config?.url === '/api/admin/account/perms')
        if (error.config?.url === '/api/admin/account/perms') {
          router.push('/account/login')
        }
        const errorResponse: ErrorResponse = {
          code: error.response?.status || 500,
          msg: error.response?.data?.msg || error.message || 'Unknown error',
        }

        ElMessage({
          message: `${errorResponse.code}:${errorResponse.msg}`,
          type: 'error',
          grouping: true,
        })

        return Promise.reject(errorResponse)
      },
    )
  }

  // 更新请求方法以正确处理响应
  public async request<T = unknown>(config: RequestConfig): Promise<T> {
    const response = await this.instance.request<BaseResponse<T>>(config)
    return response.data.data
  }

  public async get<T = unknown>(url: string, config?: RequestConfig): Promise<T> {
    const response = await this.instance.get<BaseResponse<T>>(url, config)
    return response.data.data
  }

  public async post<T = unknown, D = unknown>(
    url: string,
    data?: D,
    config?: RequestConfig,
  ): Promise<T> {
    const response = await this.instance.post<BaseResponse<T>>(url, data, config)
    return response.data.data
  }

  public async put<T = unknown, D = unknown>(
    url: string,
    data?: D,
    config?: RequestConfig,
  ): Promise<T> {
    const response = await this.instance.put<BaseResponse<T>>(url, data, config)
    return response.data.data
  }

  public async delete<T = unknown>(url: string, config?: RequestConfig): Promise<T> {
    const response = await this.instance.delete<BaseResponse<T>>(url, config)
    return response.data.data
  }

  public async patch<T = unknown, D = unknown>(
    url: string,
    data?: D,
    config?: RequestConfig,
  ): Promise<T> {
    const response = await this.instance.patch<BaseResponse<T>>(url, data, config)
    return response.data.data
  }
}

// 默认配置
const defaultConfig: AxiosRequestConfig = {
  // baseURL: import.meta.env.VITE_API_BASE_URL,
  timeout: 10000,
  withCredentials: true,
  headers: {
    'Content-Type': 'application/json;charset=UTF-8',
  },
}

export const http = new HttpClient(defaultConfig)
